/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "multi_vpn_manager.h"

#include <regex>
#include <string>

#include <fcntl.h>

#include "net_manager_constants.h"
#include "net_manager_ext_constants.h"
#include "netmgr_ext_log_wrapper.h"
#include "netsys_controller.h"
#include "ipc_skeleton.h"

namespace OHOS {
namespace NetManagerStandard {
constexpr int32_t MAX_VPN_INTERFACE_COUNT = 20;

MultiVpnManager &MultiVpnManager::GetInstance()
{
    static MultiVpnManager instance;
    return instance;
}

MultiVpnManager::MultiVpnManager()
{
}

int32_t MultiVpnManager::CreateMultiVpnInterface(const sptr<SysVpnConfig> &vpnConfig, sptr<MultiVpnInterface> &info)
{
    if (vpnConfig == nullptr) {
        NETMGR_EXT_LOG_E("CreateMultiVpnInterface failed, config is null");
        return NETMANAGER_EXT_ERR_INTERNAL;
    }
    if (multiVpnInterfaces_.size() >= MAX_VPN_INTERFACE_COUNT) {
        NETMGR_EXT_LOG_E("CreateMultiVpnInterface failed, MAX_VPN_INTERFACE_COUNT");
        return NETMANAGER_EXT_ERR_INTERNAL;
    }
    int32_t ifNameId = multiVpnInterfaces_.size();   // debug
    std::string newIfName = "";
    switch (vpnConfig->vpnType_) {
        case VpnType::IKEV2_IPSEC_MSCHAPv2:
        case VpnType::IKEV2_IPSEC_PSK:
        case VpnType::IKEV2_IPSEC_RSA:
        case VpnType::IPSEC_XAUTH_PSK:
        case VpnType::IPSEC_XAUTH_RSA:
        case VpnType::IPSEC_HYBRID_RSA:
            newIfName = "xfrm" + std::to_string(ifNameId);
            break;
        case VpnType::OPENVPN:
            newIfName = "openvpn" + std::to_string(ifNameId);
            break;
        case VpnType::L2TP_IPSEC_PSK:
        case VpnType::L2TP_IPSEC_RSA:
            newIfName = "ppp" + std::to_string(ifNameId);
            break;
        default:
            NETMGR_EXT_LOG_E("CreateMultiVpnInterface failed, invalid type=%{public}d", vpnConfig->vpnType_);
            return NETMANAGER_EXT_ERR_INTERNAL;
    }
    info = new (std::nothrow) MultiVpnInterface();
    if (info == nullptr) {
        NETMGR_EXT_LOG_E("CreateMultiVpnInterface failed, info is null");
        return NETMANAGER_EXT_ERR_INTERNAL;
    }
    info->vpnId = vpnConfig->vpnId_;
    info->ifNameId = ifNameId;
    info->ifName = newIfName;
    info->callingUid = static_cast<uint32_t>(IPCSkeleton::GetCallingUid());
    NETMGR_EXT_LOG_I("CreateMultiVpnInterface %{public}s", newIfName.c_str());
    // add
    return AddMultiVpnInterface(info);
}

int32_t MultiVpnManager::AddMultiVpnInterface(const sptr<MultiVpnInterface> &info)
{
    if (info == nullptr || info->ifName.empty()) {
        NETMGR_EXT_LOG_E("AddMultiVpnInterface failed, info invalid");
        return NETMANAGER_EXT_ERR_INTERNAL;
    }
    multiVpnInterfaces_.emplace_back(info);
    NETMGR_EXT_LOG_E("AddMultiVpnInterface %{public}s, size:%{public}d",
        info->ifName.c_str(), multiVpnInterfaces_.size());
    return NETMANAGER_EXT_SUCCESS;
}

int32_t MultiVpnManager::DelMultiVpnInterface(const sptr<MultiVpnInterface> &info)
{
    if (info == nullptr) {
        NETMGR_EXT_LOG_E("DelMultiVpnInterface failed, info invalid");
        return NETMANAGER_EXT_ERR_INTERNAL;
    }
    multiVpnInterfaces_.erase(std::remove(multiVpnInterfaces_.begin(), multiVpnInterfaces_.end(), info),
        multiVpnInterfaces_.end());
    NETMGR_EXT_LOG_I("DelMultiVpnInterface %{public}s, size:%{public}d",
        info->ifName.c_str(), multiVpnInterfaces_.size());
    return NETMANAGER_EXT_SUCCESS;
}

} // namespace NetManagerStandard
} // namespace OHOS
